﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Specialized;
using PictureManager.Core.Provider;
using System.Globalization;
using System.IO;

namespace PictureManager.Core
{
    public class PictureSettings
    {
        /// <summary>
        ///     Occurs when [changed].
        /// </summary>
        public static event EventHandler<EventArgs> Changed;

        /// <summary>
        ///     The blog settings singleton.
        /// </summary>
        /// <remarks>
        /// This should be created immediately instead of lazyloaded. It'll reduce the number of null checks that occur
        /// due to heavy reliance on calls to BlogSettings.Instance.
        /// </remarks>
        private static PictureSettings pictureSettingsSingleton;

        #region Instance

        /// <summary>
        ///     Gets the singleton instance of the <see cref = "PictureSettings" /> class.
        /// </summary>
        /// <value>A singleton instance of the <see cref = "PictureSettings" /> class.</value>
        /// <remarks>
        /// </remarks>
        public static PictureSettings Instance
        {
            get
            {
                return pictureSettingsSingleton == null ? pictureSettingsSingleton = new PictureSettings() : pictureSettingsSingleton;
            }
        }

        #endregion

        public PictureSettings()
        {
            Load();
        }

        #region Properties

        /// <summary>
        /// Gets or sets the default storage location for blog data.
        /// </summary>
        public string StorageLocation { get; set; }
        /// <summary>
        /// Gets or sets the default root node value.
        /// </summary>
        public String PictureRootNode { get; set; }

        public string StorageFolder
        {
            get
            {
                var p = StorageLocation.Replace("~/", string.Empty);
                return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, p);
            }
        }
        public string BackupLocation { get; set; }

        public string BackupFolder
        {
            get
            {
                var p = BackupLocation.Replace("~/", string.Empty);
                return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, p);
            }
        }
        public string Language { get; set; }
        #endregion

        #region Methods
        #region Load()

        private IDictionary<String, System.Reflection.PropertyInfo> GetSettingsTypePropertyDict()
        {
            var settingsType = this.GetType();

            var result = new System.Collections.Generic.Dictionary<String, System.Reflection.PropertyInfo>(StringComparer.OrdinalIgnoreCase);

            foreach (var prop in settingsType.GetProperties())
            {
                result[prop.Name] = prop;
            }

            return result;

        }

        /// <summary>
        /// Initializes the singleton instance of the <see cref="BlogSettings"/> class.
        /// </summary>
        private void Load()
        {
            // ------------------------------------------------------------
            // 	Enumerate through individual settings nodes
            // ------------------------------------------------------------
            var dic = PictureService.LoadSettings();
            var settingsProps = GetSettingsTypePropertyDict();

            foreach (System.Collections.DictionaryEntry entry in dic)
            {
                string name = (string)entry.Key;
                System.Reflection.PropertyInfo property = null;

                if (settingsProps.TryGetValue(name, out property))
                {
                    // ------------------------------------------------------------
                    // 	Attempt to apply configured setting
                    // ------------------------------------------------------------
                    try
                    {
                        if (property.CanWrite)
                        {
                            string value = (string)entry.Value;
                            var propType = property.PropertyType;

                            if (propType.IsEnum)
                            {
                                property.SetValue(this, Enum.Parse(propType, value), null);
                            }
                            else
                            {
                                property.SetValue(this, Convert.ChangeType(value, propType, CultureInfo.CurrentCulture), null);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        UtilLib.Util.Log(UtilLib.LogLevel.Error, new Exception(string.Format("Error loading blog settings: {0}", e.Message)));
                    }
                }

            }
            this.PictureRootNode = PictureService.GetPictureRootNode();
            this.StorageLocation = PictureService.GetStorageLocation();
            this.BackupLocation = PictureService.GetBackupLocation();
        }

        #endregion

        #region OnChanged()

        /// <summary>
        /// Occurs when the settings have been changed.
        /// </summary>
        private static void OnChanged()
        {
            // Execute event handler
            if (Changed != null)
            {
                Changed(null, new EventArgs());
            }
        }

        #endregion

        #region Save()

        /// <summary>
        /// Saves the settings to disk.
        /// </summary>
        public void Save()
        {
            var dic = new StringDictionary();
            var settingsType = this.GetType();

            // ------------------------------------------------------------
            // 	Enumerate through settings properties
            // ------------------------------------------------------------
            foreach (var propertyInformation in settingsType.GetProperties())
            {
                if (propertyInformation.Name != "Instance")
                {
                    // ------------------------------------------------------------
                    // 	Extract property value and its string representation
                    // ------------------------------------------------------------
                    var propertyValue = propertyInformation.GetValue(this, null);

                    string valueAsString;

                    // ------------------------------------------------------------
                    // 	Format null/default property values as empty strings
                    // ------------------------------------------------------------
                    if (propertyValue == null || propertyValue.Equals(Int32.MinValue) ||
                        propertyValue.Equals(Single.MinValue))
                    {
                        valueAsString = String.Empty;
                    }
                    else
                    {
                        valueAsString = propertyValue.ToString();
                    }

                    // ------------------------------------------------------------
                    // 	Write property name/value pair
                    // ------------------------------------------------------------
                    dic.Add(propertyInformation.Name, valueAsString);
                }
            }

            PictureService.SaveSettings(dic);
            OnChanged();
        }

        #endregion
        #endregion
    }
}
